//
//  ZTDevice.m
//  MQTTNetworkTools
//
//  Created by Yahaong on 16/8/3.
//  Copyright © 2016年 yahaong. All rights reserved.
//

#import "ZTDevice.h"
#import "MQTTCoverTool.h"
#import "DataManager.h"
#import "OperationModel.h"
#import "OperationGroup.h"
#import "DataBaseManager.h"

@implementation ZTDevice

-(void)dealloc {
    debugLogInfo(@"%s,%@,%p", __PRETTY_FUNCTION__,[[self class] description] ,self);
}

- (id)init {
    if (self = [super init]) {
    }
    return self;
}

- (instancetype __nullable)initWithApsn:(XAITYPEAPSN)apsn Luid:(XAITYPELUID)luid type:(ZTDeviceType)type
{
    if (self = [self initWithApsn:apsn Luid:luid]) {
        _devType = type;
        _name = [self originalName];
    }
    return self;
}
- (id)initWithApsn:(XAITYPEAPSN)apsn Luid:(XAITYPELUID)luid
{
    if (self = [super init]) {
        _apsn = apsn;
        _luid = luid;
    }
    return self;
}

-(id)copyWithZone:(NSZone *)zone
{
    ZTDevice* dev = [[ZTDevice allocWithZone:zone]init];
    dev.apsn = _apsn;
    dev.luid = _luid;
    dev.name = _name;
    dev.devStatus = _devStatus;
    return dev;
}

- (void) willRemove{
    [super willRemove];
}

- (NSString *)originalName {
    NSString* name = nil;
    switch (self.devType) {
        case ZTDeviceTypeOneWay0Switch:
        case ZTDeviceTypeOneWaySwitch:
            name = @"单路开关";
            break;
        case ZTDeviceTypeTwoWay0Switch:
        case ZTDeviceTypeTwoWaySwitch:
            name = @"双路开关";
            break;
        case ZTDeviceTypeThreeWay0Switch:
        case ZTDeviceTypeThreeWaySwitch:
            name = @"三路开关";
            break;
        case ZTDeviceTypeFourWay0Switch:
        case ZTDeviceTypeFourWaySwitch:
            name = @"四路开关";
            break;
        case ZTDeviceTypeOneWaySocket:
            name = @"单路插座";
            break;
        case ZTDeviceTypeTwoWaySocket:
            name = @"两路路插座";
            break;
        case ZTDeviceTypeThreeWaySocket:
            name = @"三路插座";
            break;
        case ZTDeviceTypeFourWaySocket:
            name = @"四路插座";
            break;
        case ZTDeviceTypeZTDoorsensor:
            name = @"门磁";
            break;
        case ZTDeviceTypeLCCamera:
            name = @"摄像头";
            break;
        case ZTDeviceTypeInfraredDetector:
            name = @"红外检测";
            break;
        case ZTDeviceTypeSmoke:
            name = @"烟雾探测";
            break;
        case ZTDeviceTypeAir:
            name = @"空气质量监测";
            break;
        case ZTDeviceTypeGAS:
            name = @"煤气探测";
            break;
        case ZTDeviceTypeFlooding:
            name = @"水浸检测";
            break;
        case ZTDeviceTypeAlarmkey:
            name = @"一键报警";
            break;
        case ZTDeviceTypeCurtainSingleTrack:
            name = @"单轨窗帘";
            break;
        case ZTDeviceTypeCurtainDoubleTrack:
            name = @"双轨窗帘";
            break;
        default:
            break;
    }
    return [NSString stringWithFormat:@"unknow.%@.0",name];
}

- (void)reciveACK:(XAIPKTAck* __nullable)pktAck
{
    if (nil ==  pktAck) return;
    if (pktAck.error != 0)
    {
        debugLogInfo(@"ACK出现了错误啊%zd %@",pktAck.error ,self.name);
        return;
    }
    debugLogInfo(@" recived ack %@",self.name);
    
}


- (void)reciveStatus:(uint32_t)gatewayApsn
          deviceLuid:(uint64_t )deviceLuid
         triggerApsn:( uint32_t)triggerApsn
         triggerLuid:(uint64_t)triggerLuid
           timestamp:(uint32_t)timestamp
            statusID:(uint8_t)statusID
                data:(XAITLV*__nonnull)data
           isHistory:(BOOL)isHistory
{
    if (data == nil)
    {
        debugLogInfo(@"reciveStatus 收到的数据为空");
        return;
    }
    switch (statusID) {
        case 0xff:
        {
            if (isHistory) {
                
            } else {
                const void* bytes = [data getPayloadbyte];
                if (bytes == NULL) {
                    return;
                }
                self.name = [[NSString alloc]initWithBytes:bytes length:data.payloadlen encoding:NSUTF8StringEncoding];
                [kDataManager deviceRefreshCallBackWithType:DeviceCallbackTypeName];
            }
        }
            break;
        case 0xfe:
        {
            if (isHistory) {
                
            } else {
                uint8_t status = 0;
                memcpy(&status, [data getPayloadbyte], sizeof(uint8_t));
                self.devStatus = status;
                [kDataManager deviceRefreshCallBackWithType:DeviceCallbackTypeConnectStatus];
            }
        }
            break;
        case 0xfd:
        {
            if (isHistory) {
                
            } else {

                uint8_t status = 0;
                memcpy(&status, [data getPayloadbyte], sizeof(uint8_t));
                self.devStatus = status;
                [kDataManager deviceRefreshCallBackWithType:DeviceCallbackTypePower];
            }
        }
            break;
        default:
            break;
    }
}

- (void)reciveStatus:(XAIPKTStatus* __nullable)pktStatus
{
    if (pktStatus == nil) {
        return;
    }
    XAIFormatDataCount* formatDataCount = [XAIFormatDataCount format:[pktStatus getPayloadbyte] length:pktStatus.payloadlen];
    XAITLV *tlv = [formatDataCount  getTLVAtIndex:0];
    switch (pktStatus.oprId) {
        case 0xff:
        {
            self.name = [[NSString alloc]initWithBytes:[tlv getPayloadbyte] length:tlv.payloadlen encoding:NSUTF8StringEncoding];
            debugLogInfo(@"deviceThread%@",[NSThread currentThread]);
            [kDataManager deviceRefreshCallBackWithType:DeviceCallbackTypeName];
        }
            break;
        case 0xfe:
        {   uint8_t status = 0;
            memcpy(&status, [tlv getPayloadbyte], sizeof(uint8_t));
            self.devStatus = status;
            [kDataManager callBack];
        }
            break;
        default:
            break;
    }
}

- (NSMutableArray *)findAllOperationGroup {
    NSMutableArray *groups = [NSMutableArray array];
    NSArray *operations = [kDataBaseManager loadOperationData:self.apsn luid:self.luid];
    if (operations.count == 0) {
        return groups;
    }
    for (OperationModel *oper in operations) {
        if (groups.count == 0) {
            OperationGroup *group = [[OperationGroup alloc]init];
            group.time = oper.time;
            [group.operations insertObject:oper atIndex:0];
            [groups insertObject:group atIndex:0];
        } else {
            OperationGroup *findGroup = nil;
            for (OperationGroup *group in groups) {
                BOOL isSameDay  = [self isSameDay:group.time date2:oper.time];
                if (isSameDay) {
                    findGroup = group;
                    break;
                }
            }
            if (findGroup) {
                [findGroup.operations insertObject:oper atIndex:0];
            } else {
                OperationGroup *group = [[OperationGroup alloc]init];
                group.time = oper.time;
                [group.operations insertObject:oper atIndex:0];
                [groups insertObject:group atIndex:0];
            }
        }
    }
    return groups;
}

/**
 * 是否为同一个操作
 */
- (BOOL)compareOpera:(OperationModel*)operation1 withOpera:(OperationModel*)operation2 {
    return operation1.time == operation2.time && operation1.apsn == operation2.apsn && operation1.luid == operation2.luid && operation1.triggerApsn == operation2.triggerApsn && operation1.triggerLuid == operation2.triggerLuid;
}

/**
 *  是否为同一天
 */
- (BOOL)isSameDay:(NSInteger )time1 date2:(NSInteger)time2 {
    NSDate *date1 = [NSDate dateWithTimeIntervalSince1970:time1];
    NSDate *date2 = [NSDate dateWithTimeIntervalSince1970:time2];
    NSCalendar* calendar = [NSCalendar currentCalendar];
    unsigned unitFlags =  NSCalendarUnitYear | NSCalendarUnitMonth |  NSCalendarUnitDay;
    NSDateComponents* comp1 = [calendar components:unitFlags fromDate:date1];
    NSDateComponents* comp2 = [calendar components:unitFlags fromDate:date2];
    return [comp1 day]   == [comp2 day] &&
    [comp1 month] == [comp2 month] &&
    [comp1 year]  == [comp2 year];
}

- (void)setCircuitStatus:(NSUInteger)status which:(NSUInteger)num
{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        XAITYPEBOOL typeBool = status;
        NSError* error = [kMQTTSessionManager.xai sendCMD:num toApsn:self.apsn toLuid:self.luid dataType:XAI_DATA_TYPE_BIN_BOOL bytes:&typeBool length:sizeof(typeBool)];
        if (error.code == 0) {
            NSLog(@"控制成功");
        } else {
            NSLog(@"控制失败%@",error.localizedDescription);
        }
    });
}

- (void)updateOperationWithGatewayApsn:(uint32_t)gatewayApsn
                 deviceLuid:(uint64_t )deviceLuid
                triggerApsn:(uint32_t)triggerApsn
            triggerLuid:(uint64_t)triggerLuid
              timestamp:(uint32_t)timestamp
              operation:(NSString *)oper {
    if (oper.length == 0) {
        return;
    }
    dispatch_async(kMQTTSessionManager.historyMessageQueue,^{
        OperationModel *operation = [OperationModel operationWithApsn:self.apsn luid:self.luid triggerApsn:triggerApsn triggerLuid:triggerLuid time:timestamp operation:oper];
        [kDataManager historyOperationLock];
        for (OperationGroup *group in self.operationGroups ) {
            for (OperationModel *oper in group.operations) {
                if ([self compareOpera:operation withOpera:oper]) {
                    [kDataManager historyOperationUnlock];
                    return;
                }   
            }
        }
        [kDataBaseManager insertOperationModel:operation];
        if (self.operationGroups.count == 0) {
            OperationGroup *group = [[OperationGroup alloc]init];
            group.time = timestamp;
            [group.operations insertObject:operation atIndex:0];
            [self.operationGroups addObject:group];
        } else {
            OperationGroup *findGroup = nil;
            for (OperationGroup *group in self.operationGroups) {
                BOOL isSameDay  = [self isSameDay:group.time date2:timestamp];
                if (isSameDay) {
                    findGroup = group;
                    break;
                }
            }
            if (findGroup) {
                [findGroup.operations insertObject:operation atIndex:0];
            } else {
                OperationGroup *group = [[OperationGroup alloc]init];
                group.time = timestamp;
                [group.operations insertObject:operation atIndex:0];
                [self.operationGroups insertObject:group atIndex:0];
            }
        }
        [kDataManager historyOperationUnlock];
        [kDataManager deviceHistoryOperationCallBack:gatewayApsn luid:deviceLuid];
    });
}

- (NSString *)getRoomName {
    if (self.name.length == 0) {
        debugLogInfo(@"ZTDevice 设备的名字为空");
        return nil;
    }
    NSArray *arrayName = [self.name componentsSeparatedByString:@"."];
    if(arrayName.count < 2) {
        debugLogInfo(@"ZTDevice 设备的名字格式不对");
        return nil;
    }
    return [arrayName[0] stringByReplacingOccurrencesOfString:@"\0" withString:@""];
}

- (NSString *)getDeviceName {
    if (self.name.length == 0)
    {
        debugLogInfo(@"ZTDevice 设备的名字为空");
        return @"";
    }
    NSArray *arrayName = [self.name componentsSeparatedByString:@"."];
    if(arrayName.count < 2) {
       debugLogInfo(@"ZTDevice 设备的名字格式不对");
       return @"";
    }
    return [arrayName[1] stringByReplacingOccurrencesOfString:@"\0" withString:@""];
}

#pragma mark getters and setters
- (NSMutableArray <OperationGroup *> *)operationGroups {
    if (!_operationGroups) {
        _operationGroups  = [self findAllOperationGroup];
    }
    return _operationGroups;
}
@end
